import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 钱包
 * </p>
 *
 * @author KANLEI
 * @email freefree.me@qq.com
 * @create 2020-10-28
 */
@Slf4j
@ToString
public class Wallet {

    public PrivateKey privateKey;
    public PublicKey publicKey;
    //only UTXOs owned by this wallet
    public HashMap<String,TransactionOutput> UTXOs = new HashMap<String,TransactionOutput>();

    public Wallet() {
        generateKeyPair();
    }

    public void generateKeyPair() {

        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "BC");

            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

            ECGenParameterSpec ec = new ECGenParameterSpec("prime192v1");

            generator.initialize(ec,random);

            KeyPair keyPair = generator.genKeyPair();

            publicKey = keyPair.getPublic();
            privateKey = keyPair.getPrivate();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public double getBalance() {
        double total = 0;
        for (Map.Entry<String, TransactionOutput> entry : FreeChain.UTXOs.entrySet()) {
            TransactionOutput output = entry.getValue();
            // this block belong to me
            if (output.isMine(publicKey)) {
                UTXOs.put(output.id,output);
                total += output.value;
            }
        }
        return total;
    }

    public Transaction sendFunds(PublicKey receiver, double value) {
        if (getBalance() < value) {
            log.error("Not funds to transaction.");
            return null;
        }
        if (value < FreeChain.minimumTransaction) {
            log.error("Value of transaction less than minimum transaction.");
            return null;
        }
        ArrayList<TransactionInput> inputs = new ArrayList<>();

        double total = 0;

        for (Map.Entry<String, TransactionOutput> entry : UTXOs.entrySet()) {
            TransactionOutput output = entry.getValue();
            total += output.value;
            inputs.add(new TransactionInput(output.id));
            if (total > value) break;
        }

        Transaction transaction = new Transaction(publicKey, receiver, value, inputs);
        transaction.generateSignature(privateKey);

        for (TransactionInput input : inputs) {
            UTXOs.remove(input.transactionOutputId);
        }
        return transaction;
    }

}
